package com.foreveross.chameleon.model;

import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import android.content.Context;

import com.foreveross.chameleon.config.ChameleonConfig;
import com.foreveross.chameleon.config.ChameleonConstants;
import com.foreveross.chameleon.utils.FileCopeTool;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

/**
 * @decription 应用实体类
 * @author zhouzhineng
 *
 */
public class ApplicationInfo implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -4053208530797652022L;

	private String name = null;

    private String releaseNote = null;

    private String iconUrl = null;
    
    private String bundle = null;

    private String platform = null;

    private String version = null;

    private int build = 0;

    private String identifier = null;
    
    private String appUrl = null;
    
    private String mainModuleTag = null;
    
    private String appKey = "";
    
	protected Set<ModuleInfo> modules;
	
	private  Set<ModuleInfo> installedModules;	//本地安装的模块
	
	private  Set<ModuleInfo> uninstallModules;	//尚未安装的模块
	
	private  Set<ModuleInfo> upgradeModules;	//可升级的模块
	
	private transient HashMap<String,ModuleInfo> allModules;	//服务端返回的全部模块

	public transient FileCopeTool tool;
	private transient Context context;
	private static Context mContext;
	private static ApplicationInfo mInstance;
	
	public void loadApplicationInfo() {
		if(isInstalled()) {
			System.out.println("运行时目录读取");
            name = ChameleonConstants.APPINFO_CONFIG_FILE + ".json";
            String results = tool.readerFile(ChameleonConfig.APP_PATH, name);
            ApplicationInfo info = buildApplication(results);
            info.context = this.context;
            copyProperties(info);
		} else {
			String results = tool.getFromAssets(ChameleonConstants.APPINFO_CONFIG_FILE + ".json");
            ApplicationInfo info = buildApplication(results);
            info.context = this.context;

            copyProperties(info);

            /** 安装应用信息 */
            try {
                install();
            } catch(IOException e) {
                e.printStackTrace();
            }
		}
	}
	
	public void copyProperties(ApplicationInfo info) {
        this.identifier = info.getPackageName();
        //this.build = info.getBuild();	
        this.build = info.getVersionCode();
       this.iconUrl = info.getIcon();
        this.modules = info.getModules();
        this.name = info.getName();
        this.releaseNote = info.getReleaseNote();
        this.version = info.getVersionName();
        this.platform = info.getPlatform();
        this.appKey = info.getAppKey();
        this.appUrl = info.getDownloadUrl();
        this.mainModuleTag = info.getMainModuleTag();
    }
	
	 public static ApplicationInfo buildApplication(String json) {
	        GsonBuilder builder = new GsonBuilder();
	        Gson gson = builder.create();
	        ApplicationInfo result = gson.fromJson(json, ApplicationInfo.class);
	        return result;
	}
	 
	public void compareAndSetAppInfo(ApplicationInfo remoteApp) {
		if(installedModules != null) {
			installedModules.clear();
		} else {
			installedModules = new HashSet<ModuleInfo>();
		}
		if(uninstallModules != null) {
			uninstallModules.clear();
		} else {
			uninstallModules = new HashSet<ModuleInfo>();
		}
		if(upgradeModules != null) {
			upgradeModules.clear();
		} else {
			upgradeModules = new HashSet<ModuleInfo>();
		}
		if(allModules != null) {
			allModules.clear();
		} else {
			allModules = new HashMap<String,ModuleInfo>();
		}
		
		loadApplicationInfo();
		Set<ModuleInfo> localModules = getModules();
		Set<ModuleInfo> remoteModules = remoteApp.getModules();
		Map<String,ModuleInfo> localModuleMap = new HashMap<String,ModuleInfo>();
		for(ModuleInfo module : localModules) {
			localModuleMap.put(module.getIdentifier(), module);
			if(module.getModuleType() != ModuleInfo.DELETED) {
			   allModules.remove(module.getIdentifier());
			   module.setModuleType(ModuleInfo.INSTALLED);
			   installedModules.add(module);
			   allModules.put(module.getIdentifier(), module);
			}			
		}
		ModuleInfo localModule = null;
		for(ModuleInfo remoteModule : remoteModules) {
			if(localModuleMap.containsKey(remoteModule.getIdentifier())) {
				localModule = localModuleMap.get(remoteModule.getIdentifier());
				if(localModule.getModuleType() == ModuleInfo.DELETED) {
					allModules.remove(remoteModule.getIdentifier());
					remoteModule.setModuleType(ModuleInfo.UNINSTALL);
					uninstallModules.add(remoteModule);
					allModules.put(remoteModule.getIdentifier(), remoteModule);
				} else {
					if(localModule.getBuild() < remoteModule.getBuild()) {
						allModules.remove(localModule.getIdentifier());
						remoteModule.setModuleType(ModuleInfo.UPGRADABLE);
						upgradeModules.add(remoteModule);
						allModules.put(remoteModule.getIdentifier(), remoteModule);
					}
				}

			} else {
				allModules.remove(remoteModule.getIdentifier());
				remoteModule.setModuleType(ModuleInfo.UNINSTALL);
				uninstallModules.add(remoteModule);
				allModules.put(remoteModule.getIdentifier(), remoteModule);
			}
		}
	}
	
	
	public ModuleInfo getModule(String identify) {
		for(ModuleInfo module : modules) {
			if(module.getIdentifier().equals(identify)) {
				return module;
			}
		}
		return null;
	}
	
	public void removeModule(String identify) {
		if(modules == null) {
			return;
		}
		Iterator<ModuleInfo> it = modules.iterator();
		ModuleInfo module;
		while(it.hasNext()){
	        module = it.next();
	        if(module.getIdentifier().equals(identify))
	           it.remove();   
	    }
	}
	
	public void addModule(ModuleInfo module) {
		removeModule(module.getIdentifier());
		modules.add(module);
	}
	
	/**
     * 安装应用，将文件复制到运行时目录
     */
    public void install() throws IOException {
        // 复制Assets文件夹中的Cube.json 文件到运行时目录。
        tool.copyOneFileToSDCard(ChameleonConstants.APPINFO_CONFIG_FILE + ".json",
                                 ChameleonConfig.APP_PATH + "/",
                                 ChameleonConstants.APPINFO_CONFIG_FILE + ".json"
        );

    }
	  /**
     * 判断运行时目录是否存在chameleon_appinfo_config.json 文件。
     *
     * @return
     */
    public boolean isInstalled() {
        Boolean isExist = tool.isfileExist(ChameleonConfig.APP_PATH, ChameleonConstants.APPINFO_CONFIG_FILE + ".json");
        return isExist;
    }
    
    
    public void save(ApplicationInfo info) {
        GsonBuilder builder = new GsonBuilder();
        Gson gson = builder.create();
        String json = gson.toJson(info);
        if(tool == null) {
        	tool = new FileCopeTool(mContext);
        }
        try {
            tool.writeToJsonFile(ChameleonConstants.APPINFO_CONFIG_FILE,
                                 ChameleonConfig.APP_PATH + "/",
                                 json
            );
        } catch(Exception e) {
            e.printStackTrace();
        }

    }
    
    public static ApplicationInfo getInstance(Context context) {
        if(mInstance == null) {
        	mInstance = new ApplicationInfo(context);
        }
        mInstance.loadApplicationInfo();
        return mInstance;
    }
    
    private ApplicationInfo(Context context) {
        mContext = context;
        tool = new FileCopeTool(context);

    }
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getReleaseNote() {
		return releaseNote;
	}

	public void setReleaseNote(String releaseNote) {
		this.releaseNote = releaseNote;
	}
	
	public String getIcon() {
    	return iconUrl;
    }

    public void setIcon(String icon) {
    	this.iconUrl = icon;
    }


	public String getBundle() {
		return bundle;
	}

	public void setBundle(String bundle) {
		this.bundle = bundle;
	}

	public String getPlatform() {
		return platform;
	}

	public void setPlatform(String platform) {
		this.platform = platform;
	}

	public String getVersion() {
		return version;
	}

	public void setVersion(String version) {
		this.version = version;
	}

	public int getBuild() {
		return build;
	}

	public void setBuild(int build) {
		this.build = build;
	}

	public String getIdentifier() {
		return identifier;
	}

	public void setIdentifier(String identifier) {
		this.identifier = identifier;
	}

	public String getDownloadUrl() {
		return appUrl;
	}

	public void setDownloadUrl(String appUrl) {
		this.appUrl = appUrl;
	}

	public String getMainModuleTag() {
		return mainModuleTag;
	}

	public void setMainModuleTag(String mainModuleTag) {
		this.mainModuleTag = mainModuleTag;
	}

	public Set<ModuleInfo> getModules() {
		if(modules == null) {
			modules = new HashSet<ModuleInfo>();
		}
		return modules;
	}

	public void setModules(Set<ModuleInfo> modules) {
		this.modules = modules;
	}
	
	
	public Set<ModuleInfo> getInstalledModules() {
		return installedModules;
	}
	
	public void setInstalledModules(Set<ModuleInfo> installedModules) {
		this.installedModules = installedModules;
	}

	public Set<ModuleInfo> getUninstallModules() {
		return uninstallModules;
	}

	public void setUninstallModules(Set<ModuleInfo> uninstallModules) {
		this.uninstallModules = uninstallModules;
	}

	public Set<ModuleInfo> getUpgradeModules() {
		return upgradeModules;
	}

	public void setUpgradeModules(Set<ModuleInfo> upgradeModules) {
		this.upgradeModules = upgradeModules;
	}

	public Set<ModuleInfo> getAllModules() {
		if(allModules == null) {
			return null;
		}
		Set<ModuleInfo> modules = new HashSet<ModuleInfo>();
		Set<String> keyset = allModules.keySet();
		for(String key : keyset) {
			modules.add(allModules.get(key));
		}
		return modules;
	}
	
	public String getPackageName() {
        return ChameleonConfig.APP_PACKAGENAME;
    }

    public String getVersionName() {
        return ChameleonConfig.VERSION_NAME;
    }

    public int getVersionCode() {
        return ChameleonConfig.VERSION_CODE;
    }
    
    public String getAppKey() {
        return ChameleonConfig.APP_ID;

    }

    public void setAppKey(String appKey) {
        this.appKey = appKey;
    }

}
